//
//  WebViewBridge.swift
//  ToBeBigFE
//
//  Created by mingo on 2020/2/9.
//  Copyright © 2020 com.example. All rights reserved.
//

import Foundation
import WebKit

protocol BridgeModule : class {
    func callFunc(_ funcName: String, callbackId: String, arg: [String: Any?])
}

class BridgeModuelBase : BridgeModule {
    weak var webView: WKWebView?
    
    func callback(callbackId: String, value: Int) {
        execJS("window.\(callbackId)(\(value))")
    }
    
    func callback(callbackId: String, value: Bool) {
        execJS("window.\(callbackId)(\(value))")
    }
    
    func callback(callbackId: String, value: String?) {
        if value == nil {
            execJS("window.\(callbackId)(null)")
        } else {
            execJS("window.\(callbackId)('\(value!)')")
        }
    }
    
    func callback(callbackId: String, json: [String:Any?]) {
        guard let jsonData = try? JSONSerialization.data(withJSONObject: json, options: []) else {
            return
        }
        guard let jsonString = String(data: jsonData, encoding: .utf8) else {
            return
        }
        execJS("window.\(callbackId)(\(jsonString))")
    }
    
    func execJS(_ script: String) {
        print("WebView execJS: \(script)")
        webView?.evaluateJavaScript(script)
    }
    
    func callFunc(_ funcName: String, callbackId: String, arg: [String: Any?]) {}
}

class BridgeHandler : NSObject, WKScriptMessageHandler {
    
    weak var webView: WKWebView?
    weak var viewController: WebViewController?
    var moduleDict = [String:BridgeModuelBase]()
    
    func initModules() {
        moduleDict["UI"] = JSBridgeUI(viewController: viewController!)
        moduleDict["KVDB"] = JSBridgeKVDB(viewController: viewController!)
        moduleDict["Camera"] = JSBridgeCamera(viewController: viewController!)
        moduleDict["Image"] = JSBridgeImage(viewController: viewController!)
    }
    
    func userContentController(
        _ userContentController: WKUserContentController,
        didReceive message: WKScriptMessage)
    {
        // 3. guard防止不合法调用和deinit后调用
        guard
            let body = message.body as? [String: Any],
            let webView = self.webView,
            let viewController = self.viewController,
            let callbackId = body["callbackId"] as? String,
            let method = body["method"] as? String,
            let data = body["data"] as? String,
            let utf8Data = data.data(using: .utf8)
        else {
            return
        }
        print("WebView callNative ok. body is \(body)")
        
        // 4. do catch，防止解析data出错
        var arg: [String:Any?]?
        do {
            arg = try JSONSerialization.jsonObject(with: utf8Data, options: []) as? [String:Any?]
        } catch (let error) {
            print(error)
            return
        }
        
        let split = method.split(separator: ".")
        let moduleName = String(split[0])
        let funcName = String(split[1])
        
        // 5. guard 优化
        guard let module = moduleDict[moduleName] else {
            return
        }
        // 6. 默认arg为空Dictionary
        module.webView = webView
        module.callFunc(funcName, callbackId: callbackId, arg: arg ?? [String:Any?]())
    }
}
